/*
   Copyright (C) 2009 Klaus Blindert <klaus.blindert@web.de>

   Part of the libABF project.

   libABF is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the
   Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef ABF_FLAT_HPP
#define ABF_FLAT_HPP

#include <abf/abf.h>
#include <string>

namespace abf
{

class flat
{
private:
    abf_flat_t* m_flat;

public:
    flat();
    flat(abf_flat_t* _flat);

    ~flat();

    flat& operator=(const flat& c);
    void clear();

    /**
      * Test wether errors occured.
      */
    bool ok () const;

    /**
      * Return error code (or ABF_E_OK).
      */
    abf_status getstatus () const;

    /**
      * Dump the contents of the flat to @b stdout.
      */
    void dump (int recurse = ABF_NOLIMIT);
    /**@}*/

    /**
      * @name Methods to flatten data
      */
    /**@{*/
    /**
    * Store a boolean value.
    * @param name id used to retrieve the value later on.
    * @param b value to store.
    */
    void put_bool (const std::string& name, bool b);

    /**
      * Store 8 bit unsigned integer value.
      * @param name id used to retrieve the value later on.
      * @param i value to store.
      */
    void put_uint8 (const std::string& name, u_int8 i);

    /**
      * Store 8 bit signed integer value.
      * @param name id used to retrieve the value later on.
      * @param i value to store.
      */
    void put_sint8 (const std::string& name, s_int8 i);

    /**
      * Store 16 bit unsigned integer value.
      * @param name id used to retrieve the value later on.
      * @param i value to store.
      */
    void put_uint16 (const std::string& name, u_int16 i);

    /**
      * Store 16 bit signed integer value.
      * @param name id used to retrieve the value later on.
      * @param i value to store.
      */
    void put_sint16 (const std::string& name, s_int16 i);

    /**
      * Store 32 bit unsigned integer value.
      * @param name id used to retrieve the value later on.
      * @param i value to store.
      */
    void put_uint32 (const std::string& name, u_int32 i);

    /**
      * Store 32 bit signed integer value.
      * @param name id used to retrieve the value later on.
      * @param i value to store.
      */
    void put_sint32 (const std::string& name, s_int32 i);

    /**
      * Store character string.
      * @param name id used to retrieve the value later on.
      * @param s string to store.
      */
    void put_string (const std::string& name, const std::string& s);

    /**
      * Store floating point value.
      * @param name id used to retrieve the value later on.
      * @param f value to store.
      */
    void put_float (const std::string& name, float f);

    /**
      * Store double value.
      * @param name id used to retrieve the value later on.
      * @param d value to store.
      */
    void put_double (const std::string& name, double d);

    /**
      * Store binary data of arbitrary length.
      * @param name id used to retrieve the value later on.
      * @param b binary data to store.
      * @param size length of data stored.
      */
    void put_block (const std::string& name, void *b, u_int32 size);

    /**
      * Store another flat. Used to create nested structures for easier
      * and safer value retrieval.
      * @param name id used to retrieve the value later on.
      * @param out flat to store.
      */
    void put_flat (const std::string& name, abf_flat_t* sub);
    /**@}*/

    /**
      * @name Methods to retrieve flattened data
      */
    /**@{*/
    /**
      * Retrieve a boolean value previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @param optional whether to gracefully ignore missing data.
      * @return value stored or \b false on error.
      */
    bool get_bool (const std::string& name);

    /**
      * Retrieve a boolean value previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @param optional default value.
      * @return value stored or \b default on error.
      */
    bool get_bool (const std::string& name, bool optional);

    /**
      * Retrieve 8 bit unsigned integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b 0 on error.
      */
    u_int8 get_uint8 (const std::string& name);

    /**
      * Retrieve 8 bit unsigned integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @param optional default value.
      * @return value stored or \b 0 on error.
      */
    u_int8 get_uint8 (const std::string& name, u_int8 optional);

    /**
      * Retrieve 8 bit signed integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b -1 on error.
      */
    s_int8 get_sint8 (const std::string& name);


    /**
      * Retrieve 8 bit signed integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @param optional default value.
      * @return value stored or \b optional on error.
      */
    s_int8 get_sint8 (const std::string& name, s_int8 optional);

    /**
      * Retrieve 16 bit unsigned integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b 0 on error.
      */
    u_int16 get_uint16 (const std::string& name);

    /**
      * Retrieve 16 bit unsigned integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b optional on error.
      */
    u_int16 get_uint16 (const std::string& name, u_int16 optional);

    /**
      * Retrieve 16 bit signed integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b -1 on error.
      */
    s_int16 get_sint16 (const std::string& name);

    /**
      * Retrieve 16 bit signed integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b -1 on error.
      */
    s_int16 get_sint16 (const std::string& name, s_int16 optional);

    /**
      * Retrieve 32 bit unsigned integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b 0 on error.
      */
    u_int32 get_uint32 (const std::string& name);

    /**
      * Retrieve 32 bit unsigned integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b optional on error.
      */
    u_int32 get_uint32 (const std::string& name, u_int32 optional);

    /**
      * Retrieve 32 bit signed integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b -1 on error.
      */
    s_int32 get_sint32 (const std::string& name);

    /**
      * Retrieve 32 bit signed integer previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b -1 on error.
      */
    s_int32 get_sint32 (const std::string& name, s_int32 optional);

    /**
      * Retrieve string previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b "" (empty string) on error.
      */
    std::string get_string (const std::string& name);

    /**
      * Retrieve string previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b "" (empty string) on error.
      */
    std::string get_string (const std::string& name, const std::string& optional);

    /**
      * Retrieve floating point number previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b 0.0 on error.
      */
    float get_float (const std::string& name);

    /**
      * Retrieve floating point number previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b 0.0 on error.
      */
    float get_float (const std::string& name, float optional);

    /**
      * Retrieve double value previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b 0.0 on error.
      */
    double get_double (const std::string& name);

    /**
      * Retrieve double value previously stored with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b 0.0 on error.
      */
    double get_double (const std::string& name, double optional);

    /**
      * Retrieve a nested flat with given id. Call
      * success() to check whether value retrieval was successful.
      * @param name id used to retrieve the value later on.
      * @return value stored or \b empty flat on error.
      */
    flat get_flat (const std::string& name);
    /**@}*/


    /**
      * Retrieve the internal C object.
      * @return abf_flat.
      */
    abf_flat_t* internal_flat();

private:
    /**
      *  Copy constructor is private - this avoids bugs.
      */
    flat(const flat& c);
};

}

#endif // ABF_FLAT_HPP
